/********************************************************************\
                            Includes
\********************************************************************/
#include <QtOpenGL>
#include <QTimer>
#include <QDebug>
#include <math.h>
#include "widget.h"

/********************************************************************\
                             defines
\********************************************************************/
#define RPI_RED    188/255.0
#define RPI_GREEN   17/255.0
#define RPI_BLUE    66/255.0
#define RPI_RADIUS       2.0
#define HUBBEL_RADIUS    1.0

/********************************************************************\
                           static Members
\********************************************************************/
GLUquadricObj *sQuadricRpi = NULL;
int            sRpiSphere  = 0;

/********************************************************************\
                          Implementation
\********************************************************************/

/*--------------------------------------------------------------------
*/
GlRpiWidget::GlRpiWidget(QWidget *parent)
    : QGLWidget(parent)
{
  setFocus();
  grabKeyboard();
  setMouseTracking(true);
  grabMouse(QCursor(Qt::BlankCursor));
  setAutoBufferSwap ( true ); 

  qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );

  // set DoubleBuffer:
  QGLFormat f = format();
  f.setDoubleBuffer(true);
  setFormat(f);
 
  QTimer *timer = new QTimer(this);
  connect(timer, SIGNAL(timeout()),
          this, SLOT(updateGL()));
  timer->start(50);

}

/*--------------------------------------------------------------------
*/
GlRpiWidget::~GlRpiWidget()
{
  makeCurrent();
}

/*--------------------------------------------------------------------
*/
QSize GlRpiWidget::minimumSizeHint() const
{
  return QSize(50, 50);
}

/*--------------------------------------------------------------------
*/
QSize GlRpiWidget::sizeHint() const
{
  return QSize(400, 400);
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::initializeGL()
{
  // Center
  move(QApplication::desktop()->width()/2 - width()/2, 
       QApplication::desktop()->height()/2- height()/2);

  glEnable(GL_DEPTH_TEST);
  
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60.0,width()/height(),0.01,60);

  glMatrixMode(GL_MODELVIEW);

  // Erstellen des Sphere-Quadrics:
  if (!sQuadricRpi) {
    sQuadricRpi = gluNewQuadric();
    gluQuadricNormals(sQuadricRpi, GLU_SMOOTH);
    sRpiSphere = glGenLists(1);
    glNewList(sRpiSphere, GL_COMPILE);
      gluQuadricOrientation(sQuadricRpi,GLU_OUTSIDE);
      gluSphere(sQuadricRpi,0.8,18,18);
    glEndList();
  }

  // Beleuchtung initialisieren:
  initLight();
  initMaterial();

  glEnable(GL_COLOR_MATERIAL); // glColor in Beleuchtung mitaufnehmen
  glClearColor(0.9,0.9,0.9,0); // Hintergrund grau
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::paintGL()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // rotierende Kamera positionieren:
  static float rotation = 0;
  rotation += 0.01;
  GLfloat pos[4] =
        { 5*cos(rotation), 5.0,   5*sin(rotation), 1.0f };
    glLightfv(GL_LIGHT0, GL_POSITION, pos);
  gluLookAt(pos[0],pos[1],pos[2],0,0,0,0,1,0);

  // Beere rendern:
  drawRpi();

  // Siehe http://bugreports.qt.nokia.com/browse/QTBUG-5002
  glDisable(GL_DEPTH_TEST);
  drawTexts();
  glEnable(GL_DEPTH_TEST);
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::drawRpi()
{
  glColor4f(RPI_RED,RPI_GREEN,RPI_BLUE,1.0);

  // Aequator:
  for (float a=0; a<360; a+=60)
    drawSphere(a,1,RPI_RADIUS,0,0); 

  // Zwischenreihe oben und unten
  for (float a=0; a<360; a+=60)
    drawSphere(a+30,1,RPI_RADIUS*0.707,RPI_RADIUS*0.707,0);
  for (float a=0; a<360; a+=60)
    drawSphere(a+30,1,RPI_RADIUS*0.707,-RPI_RADIUS*0.707,0);

  // Einzelhubbel oben und unten
  drawSphere(0,1,0, RPI_RADIUS,0);
  drawSphere(0,1,0,-RPI_RADIUS,0);

  // schwarzer Koerper:
  glColor3f(0.0,0.0,0.0);
  drawSphere(0,RPI_RADIUS+HUBBEL_RADIUS,0,0,0);

  // Koordinatensystem, gut fuers Debugging:
  /*
  glBegin(GL_LINES);
    // X-Achse:
    glColor3f(1.0,0.0,0.0);
    glVertex3f(0,0,0); glVertex3f(0,5,0);

    // Y-Achse:
    glColor3f(0.0,1.0,0.0);
    glVertex3f(0,0,0); glVertex3f(5,0,0);

    // Z-Achse:
    glColor3f(0.0,0.0,1.0);
    glVertex3f(0,0,0); glVertex3f(0,0,5);
  glEnd(); 
  */
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::drawTexts()
{
  glColor4f(1.0,0.0,0.0,1.0);
  renderText(15,15,QString("hackbeere"));
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::resizeGL(int w, int h)
/*
  Perspektive korrigieren, sonst wirkt die Scene verzerrt..
*/
{
  glViewport(0, 0, w, h);
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60.0,width()/(float)height(),0.01,60);

  glMatrixMode(GL_MODELVIEW);
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::keyPressEvent(QKeyEvent *event)
{
  if (event->key() == Qt::Key_Escape) {
    qApp->quit();
  }

  if (event->key() == Qt::Key_F) {
    if (!isFullScreen())
      showFullScreen();
    else
      showNormal();
  }
}

/********************************************************************\
                            Private
\********************************************************************/

/*--------------------------------------------------------------------
*/
void GlRpiWidget::drawSphere(float alpha, float scale,
                             float tx, float ty, float tz)
{
  glPushMatrix();
  glRotatef(alpha,0,1,0);
  glTranslatef(tx,ty,tz);
  glScalef(scale,scale,scale);
  glCallList(sRpiSphere);
  glPopMatrix();
}
    
/*--------------------------------------------------------------------
*/
void GlRpiWidget::initLight()
{
  glEnable(GL_LIGHTING);

  GLfloat ambient[4]  = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat diffuse[4]  = { 0.6, 0.4, 0.2, 1.0 };
  GLfloat specular[4] = { 0.6, 0.6, 0.4, 1.0 };

  glEnable(GL_LIGHT0);
  glLightfv(GL_LIGHT0, GL_AMBIENT,  ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE,  diffuse);
  glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
}

/*--------------------------------------------------------------------
*/
void GlRpiWidget::initMaterial()
{
  GLfloat globalAmbient[4] = {0.0, 0.0, 0.0, 1.0};
  GLfloat ambient[4]       = {1.0, 1.0, 1.0, 1.0};
  GLfloat diffuse[4]       = {1.0, 1.0, 1.0, 1.0};
  GLfloat specular[4]      = {1.0, 1.0, 1.0, 1.0};

  // Globale ambiente Beleuchtung
  // komplett herunternehmen
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT,
                 globalAmbient);

  // Materialparameter setzen
  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);
  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse);
  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);
  glMaterialf (GL_FRONT_AND_BACK,GL_SHININESS,16.0f);
}

